import pandas as pd
import numpy as np
import warnings
import ftplib, os,sys
import sys
sys.path.extend(['pyd所在路径'])
warnings.filterwarnings('ignore')

# from PorOpt.OptimizationEnhance import PortfolioOpt
from OptimizationEnhance import PortfolioOpt,prepareParam,_load_Barra


if __name__ == '__main__':
    base_dir = 'D:\工作文档\业绩归因\data_22/'
    # 输出路径

    portfolio = 'csi800w'
    benchmark = 'CSI500Weight'
    alpha_tag = None#'csi300shrs'
    industry = '中信行业分类'
    date = '20210930'
    stk_up = 0.1  # 个股权重上限
    stk_low = 0.001  # 个股权重下限
    num_limit_lb = 20  # 股票数量上限
    num_limit_ub = 300  # 股票数量上限
    ind_bound = 0.08  # 行业偏离限制 可自定义DataFrame对不同行业设置不同偏离
    styleBound = 0.05  # 风格偏离 可自定义DataFrame对不同风格设置不同偏离
    turnover_limit = 0.6
    risk_aver = 1
    obj_type = 'MFE-R'  # 可选项'MR','MFE','MFE-R','MFE-Risk-Turnover'
    constrain_order = ['风格约束', '行业约束', '个股上限约束', '个股下限约束', '股票数量约束', '换手约束', ]
    adjust = []

    # adjust = bool(adjust)
    stk_up, stk_low, num_limit_lb, num_limit_ub, ind_bound, styleBound, turnover_limit, risk_aver = \
        [float(x) for x in
         [stk_up, stk_low, num_limit_lb, num_limit_ub, ind_bound, styleBound, turnover_limit, risk_aver]]

    out_dir = f'{base_dir}/reports/{portfolio}_base_{benchmark}_Opt/'
    os.makedirs(out_dir, exist_ok=True)

    ind_df, b_weight, h_pool, alpha = prepareParam(date, base_dir, industry, alpha_tag, benchmark, portfolio)
    # 行业约束
    indBound = pd.DataFrame(ind_bound, index=ind_df.columns, columns=['ub', 'lb'])
    indBound['lb'] = indBound['lb'] * -1
    delta, factor_cov, style_exposure, sector = _load_Barra(date, f'{base_dir}/factor\CNE7\sm\daily/')
    st_bound = pd.DataFrame({'ub': styleBound, 'lb': -styleBound}, index=style_exposure.columns)

    alpha = pd.Series(np.random.random(delta.shape[0]),index= delta.index)
    # # 单个板块

    import time

    e = time.time()


    self = PortfolioOpt(delta, factor_cov, style_exposure, ind_df, b_weight, h_pool, alpha,
                        extra_expoture=None, specific_industry=None,mixInteMode=False)

    # 用seires形式输入，可自定义每种风格、每个行业的限制

    res = self.Opt(st_bound, indBound, [stk_low, stk_up], [num_limit_lb, num_limit_ub], None, obj_type,
                   verbose=False,
                   adjust=['换手约束'], soft_constrain=constrain_order, turnover_limit=1, riskAv=risk_aver,consider_delta=True)
    total = time.time() - e
    print(total)
